package com.sina.mysql.utils;

import java.util.*;

/**
 * @ClassName ResultCode
 * @Description:
 * @Author 段浩杰
 * @Date 2018/8/22 17:44
 * @Version 1.0
 */
public enum ResultCode implements CodeEnum {

    ok(200, "成功"),


    /* 常见的客户端错误 */
    clientError(400, "客户端错误"),
    notFound(404, "未找到处理器"),
    methodNotAllowed(405, "方法不允许"),
    notAcceptable(406, "不能生成客户端需要的媒介"),

    unsupportedMedia(415, "媒介类型不被支持"),
    requestBodyError(418, "请求body错误"),
    dataExists(419, "数据已存在"),
    dataError(420, "数据错误"),

    dataValidateError(421, "数据校验错误"),
    invalidSignature(422, "客户端签名无效"),
    uploadError(423, "上传错误"),
    //客户端在我方服务器上没有存储其公钥,这种情况是非法访问
    notFoundPublicKey(424,"未找到客户端的公钥"),


    /* 服务端错误 */
    serverError(500, "服务端错误"),
    serviceUnavailable(503, "过载或down机"),
    timeout(504, "服务超时"),
    dataAccessError(510, "数据访问错误"),

    responseBodyError(511, "响应body出错"),
    signatureError(512,"生成签名错误"),
    //服务端生成响应报文时,没有找到相应的私钥为签名响应消息,则返回此码
    notFoundPrivateKey(513,"未找到与客户端匹配的服务端私钥"),


    /*############################ 网络调用(调用第三方)[800-899] start #############################################*/
    noResponse(800, "服务提供方无响应消息"),
    responseMsgError(810,"服务提供方响应消息有误"),
    /*############################ 网络调用(调用第三方)[800-899] end #############################################*/

    /*############################ 邮件状态类[900-999] start #############################################*/
    emailSendFailure(900, "邮件发送失败"),
    /*############################ 邮件状态类[900-999] end #############################################*/

    /*############################ 业务状态类[1000-1499](如:业务锁定,不可用等,具体的业务 code 不要放在这里 .) start #############################################*/
    businessLocked(1000, "业务维护中,请期待"),

    /*############################ 业务状态类[1000-1499](如:业务锁定,不可用等,具体的业务 code 不要放在这里 .) end #############################################*/


    /*----------------------------- 账户类状态类[1500-2999](如:账户锁定) end ----------------------------------------------*/

    noAccount(1500, "用户未开户"),
    noTradePwd(1501, "请先设置交易密码"),
    accountLocked(1502, "您的账户已锁定"),
    noUsableBankCard(1503, "您已解绑银行卡"),
    tradePwdNotMatch(1504, "交易密码不匹配"),
    userMinor(1505, "根据相关法规，不允许未成年投资理财。"),
    accountFreeze(1506, "您的账户存在风险，已冻结"),

    restrictWithdraw(1507, "您的提现受限"),
    balanceLack(1508, "余额不足"),
    withdrawUpper(1509, "提现超过上限"),
    withdrawLower(1510, "提现超过下限"),

    withdrawCountUpper(1511, "提现次数超过上限"),


    hadOpenAccount(1512, "用户已开户"),
    identitiesCardHadExist(1513, "开户证件信息已存在"),
    notCheckBankcard(1514, "未找到银行卡信息"),
    failCheckSign(1515, "验签失败"),
    signError(1516, "签名失败"),

    openAccountFail(1517, "开户失败"),
    bankcardUnbinded(1518, "未找到有效银行卡"),
    unauthorized(1519, "该用户未授权给系统"),
    usernotexist(1520 , "未找到用户信息" ),
    accountnotexist(1521 , "未找到账户信息" ),

    /*----------------------------- 账户类状态类[1500-2999](如:账户锁定) end ----------------------------------------------*/

    /*----------------------------- 存管业务异常[3000-3099] start ----------------------------------------------*/


    /*----------------------------- 存管业务异常[3000-3099] end ----------------------------------------------*/

    /*----------------------------- 第三方业务异常[3100-3200] start ----------------------------------------------*/
    projectExists(3100, "标的已存在"),
    projectNotExists(3101, "标的不存在"),
    projectTypeNotExists(3102, "标的类型不存在"),
    typeNotMatchProject(3103, "标的类型与渠道不匹配"),

    generalError(3104, "通用错误，错误信息可自定义"),
    projectRepayStatusError(3105, "标的当前状态非还款中"),
    prepaymentPrincipalAmountError(3106, "提前还款本金金额不匹配"),
    prepaymentInterestAmountError(3107, "提前还款利息金额不匹配"),

    prepaymentFeeAmountError(3108, "提前还款服务费金额不匹配"),
    overdueRepaymentCompensatoryError(3109, "逾期还款当期未找到已代偿支付记录")
    ;


    /*----------------------------- 第三方业务异常[3100-3200] end ----------------------------------------------*/

    private static final Set<Integer> PRESERVE = initPreserve();

    private static final Map<Integer, ResultCode> CODE_MAP;


    static {
        ResultCode[] resultCodes = values();
        Map<Integer, ResultCode> codeMap = new HashMap<>((int) (resultCodes.length / 0.75f));

        for (ResultCode resultCode : values()) {
            if (codeMap.containsKey(resultCode.code())) {
                throw new RuntimeException(String.format("code[%s] duplicate", resultCode.code()));
            }
            if (PRESERVE.contains(resultCode.code())) {
                throw new RuntimeException(String.format("code[%s] preserve", resultCode.code()));
            }
            codeMap.put(resultCode.code, resultCode);
        }
        CODE_MAP = Collections.unmodifiableMap(codeMap);
    }

    private static Set<Integer> initPreserve() {
        Set<Integer> set = new HashSet<>();
        set.add(100);
        set.add(101);

        set.add(201);
        set.add(202);
        set.add(203);
        set.add(204);

        set.add(205);
        set.add(206);

        set.add(301);
        set.add(302);
        set.add(303);
        set.add(304);

        set.add(305);
        set.add(306);
        set.add(307);


        set.add(402);
        set.add(403);
        set.add(407);
        set.add(408);

        set.add(409);
        set.add(410);
        set.add(411);
        set.add(412);

        set.add(413);
        set.add(414);
        set.add(416);

        set.add(417);


        set.add(501);
        set.add(502);
        set.add(505);

        return Collections.unmodifiableSet(set);
    }

    private final int code;

    private final String display;

    ResultCode(int code, String display) {
        this.code = code;
        this.display = display;
    }


    @Override
    public int code() {
        return code;
    }

    @Override
    public String display() {
        return display;
    }


    public static ResultCode  resolve(int code) {
        return CODE_MAP.get(code);
    }


}